﻿using System;
using ICSharpCode.SharpZipLib.Zip;
using System.IO;
using System.Threading;

namespace Com.Lancetinc.Evs.Helpers
{
    /// <summary>
    /// 文件压缩
    /// </summary>
    public static class CompressHelper
    {
        /// <summary>
        /// 压缩
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="zipFile"></param>
        /// <param name="password"></param>
        /// <param name="progress">进度</param>
        /// <param name="ct"></param>
        public static void Zip(DirectoryInfo dir, string zipFile,
            string password = null,
            IProgress<float> progress = null,
            CancellationToken? ct = null)
        {
            ct = ct ?? CancellationToken.None;
            DirUtil.EnsureDirectoryExists(new FileInfo(zipFile).DirectoryName);

            var zfe = new ZipEntryFactory { IsUnicodeText = true };
            FastZip fastZip;
            if (progress == null)
            {
                fastZip = new FastZip() { EntryFactory = zfe };
            }
            else
            {
                int totalFiles = CounterFilesInDir(dir);
                var events = new FastZipEvents();
                int finishedCount = 0;
                events.Progress = (s, e) =>
                {
                    if (ct.Value.IsCancellationRequested)
                        e.ContinueRunning = false;
                };
                events.CompletedFile = (sender, args) =>
                {
                    if (ct.Value.IsCancellationRequested)
                        args.ContinueRunning = false;

                    finishedCount++;
                    progress.Report(finishedCount * 1F / totalFiles);
                };
                fastZip = new FastZip(events) { EntryFactory = zfe };
            }

            if (!string.IsNullOrEmpty(password))
            {
                fastZip.Password = password;
            }
            fastZip.CreateEmptyDirectories = true;

            fastZip.CreateZip(zipFile, dir.FullName, true, null);
        }

        /// <summary>
        /// 解压
        /// </summary>
        /// <param name="zipFile"></param>
        /// <param name="unzipDir"></param>
        /// <param name="password"></param>
        public static void UnZip(string zipFile, DirectoryInfo unzipDir, string password = null)
        {
            DirUtil.EnsureDirectoryExists(unzipDir.FullName);

            var zfe = new ZipEntryFactory { IsUnicodeText = true };
            FastZip fastZip = new FastZip() { EntryFactory = zfe };
            if (!string.IsNullOrEmpty(password))
            {
                fastZip.Password = password;
            }
            fastZip.CreateEmptyDirectories = true;
            fastZip.ExtractZip(zipFile, unzipDir.FullName, null);
        }

        /// <summary>
        /// 统计文件夹中文件总个数
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        private static int CounterFilesInDir(DirectoryInfo dir)
        {
            int count = dir.GetFiles().Length;
            foreach (var subDir in dir.GetDirectories())
            {
                count += CounterFilesInDir(subDir);
            }
            return count;
        }
    }
}
